/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package z.h.w.jar.kit.clazz.security;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import z.h.w.jar.kit.clazz.Split;
import z.h.w.jar.kit.method.Num;
import z.h.w.jar.kit.method.To;

/**
 *
 * @author EnzoZhong
 */
public class GyrateCode {

      final public static Character space = '♡';

      public static GyrateCode born () {
            return new GyrateCode ();
      }

      public String 加密 ( String text , Integer gyrate , Boolean delSpace ) {
            String code = process ( text , gyrate );
            return delSpace ? code.replaceAll ( space.toString () , "" ) : code;
      }

      public String 加密 ( String text , Integer gyrate ) {
            return 加密 ( text , gyrate , false );
      }

      public String 解密 ( String text , Integer gyrate ) {
            return process ( text , gyrate ).replaceAll ( space.toString () , "" );
      }

      private String process ( String text , Integer gyrate ) {
            Integer len = text.replaceAll ( space.toString () , "" ).length ();
            List< List<Character>> convert = convert ( text , miniSquare ( len ) );
            Character[][] matrice = toMatrice ( convert );
            for ( Integer x = 0 ; x < gyrate ; x ++ ) {
                  matrice = turnRight ( matrice );
            }
            return array2String ( matrice );
      }

      private Character[][] turnRight ( Character[][] input ) {
            Character[][] temp = input.clone ();
            Integer lenH = temp.length;
            Integer lenL = temp[0].length;
            Character[][] newArray = new Character[ lenL ][ lenH ];
            for ( Integer x = 0 ; x < lenL ; x ++ ) {
                  for ( Integer y = 0 ; y < lenH ; y ++ ) {
                        newArray[x][y] = temp[y][lenL - 1 - x] == null ? space : temp[y][lenL - 1 - x];
                  }
            }
            return newArray;
      }

      private List< List<Character>> convert ( String text , Integer sp ) {
            while ( text.length () != sp * sp ) {
                  text = text + space;
            }
            Integer len = text.length ();
            List<Character> arrayList = Arrays.asList ( To.string2CharacterArray ( text ) );
            Split<Character> split = new Split<> ( arrayList , sp );
            List<Character> tempList;
            List< List<Character>> finalList = new ArrayList<> ( len );
            while ( split.hasNext () ) {
                  tempList = split.next ();
                  List<Character> putList = new ArrayList<> ( len );
                  for ( Character ch : tempList ) {
                        putList.add ( ch );
                  }
                  finalList.add ( putList );
            }
            return finalList;
      }

      private Character[][] toMatrice ( List< List<Character>> input ) {
            Integer rowLen = input.size ();
            Integer columnLen = input.get ( 0 ).size ();

            Character[][] re = new Character[ rowLen ][ columnLen ];
            for ( Integer x = 0 ; x < rowLen ; x ++ ) {
                  for ( Integer y = 0 ; y <= columnLen - 1 ; y ++ ) {
                        try {
                              re[x][y] = input.get ( x ).get ( y );
                        } catch ( Exception e ) {
                        }
                  }
            }
            return re;
      }

      private String array2String ( Character[][] input ) {
            StringBuffer stringBuffer = new StringBuffer ();
            Character[][] temp = input.clone ();
            for ( Integer x = 0 ; x < temp.length ; x ++ ) {
                  for ( Integer y = 0 ; y < input[x].length ; y ++ ) {
                        stringBuffer.append ( input[x][y] );
                  }
            }
            return stringBuffer.toString ();
      }

      private void show ( Character[][] input ) {
            Character[][] temp = input.clone ();
            for ( Integer x = 0 ; x < temp.length ; x ++ ) {
                  for ( Integer y = 0 ; y < input[x].length ; y ++ ) {
                        System.out.print ( input[x][y] + " " );
                  }
                  System.out.println ( "" );
            }
            System.out.println ( "" );
      }

      private Integer miniSquare ( Integer x ) {
            while (  ! Num.isInteger ( Math.sqrt ( x ) ) ) {
                  x ++;
            }
            return new Double ( Math.sqrt ( x ) + 0.5 ).intValue ();
      }

}
